package com.wecan.components.pay.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSONObject;
import com.wecan.api.saasdata.BusinessExceptionData;
import com.wecan.api.saasdata.OrderData;
import com.wecan.base.PO.BusinessException;
import com.wecan.base.PO.Order;
import com.wecan.base.VO.PayVO;
import com.wecan.base.constants.RedisKey;
import com.wecan.base.enums.ExceptionType;
import com.wecan.base.enums.OrderStatus;
import com.wecan.base.model.Result;
import com.wecan.cache.utils.RedisUtil;
import com.wecan.components.pay.DTO.UnifiedOrderDTO;
import com.wecan.components.pay.model.WxNotifyResult;
import com.wecan.components.pay.service.PayService;
import com.wecan.components.pay.service.ProcessOrderService;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;

/**
 * @Author liuzhihao
 * @Date 2022.02.22
 * @Version ${version}
 * @Description ${description}
 */
@RestController
@RequestMapping(value = "/pay")
public class PayController {

    @Autowired
    private PayService payService;

    @Autowired
    private OrderData orderData;

    @Autowired
    private ProcessOrderService processOrderService;

    @Autowired
    private BusinessExceptionData businessExceptionData;

    @Autowired
    private RedisUtil redisUtil;

    @PostMapping(value = "/wx/notify")
    public WxNotifyResult wxNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        WxNotifyResult notifyResult = new WxNotifyResult();
        try {
            JSONObject jsonObject = payService.verify(request);
            String eventType = jsonObject.getString("eventType");
            JSONObject data = jsonObject.getJSONObject("data");
            if ("TRANSACTION.SUCCESS".equals(eventType)) {
                // 支付成功
                boolean result = processOrderService.processWxOrder(data);
                if (!result) {
                    response.setStatus(HttpStatus.HTTP_INTERNAL_ERROR);
                    notifyResult.setCode("ERROR");
                    notifyResult.setMessage("失败");
                    return notifyResult;
                }
            } else if ("REFUND.SUCCESS".equals(eventType)) {
                // 退款成功
                boolean result = processOrderService.processRefundOrder(data);
                if (!result) {
                    response.setStatus(HttpStatus.HTTP_INTERNAL_ERROR);
                    notifyResult.setCode("ERROR");
                    notifyResult.setMessage("失败");
                    return notifyResult;
                }
            } else if ("REFUND.ABNORMAL".equals(eventType)) {
                // 退款失败
                BusinessException businessException = new BusinessException();
                businessException.setPrimaryId(NumberUtils.toLong(data.getString("out_trade_no")));
                businessException.setType(ExceptionType.REFUND);
                businessExceptionData.add(businessException);
            }
            response.setStatus(HttpStatus.HTTP_OK);
            notifyResult.setCode("SUCCESS");
            notifyResult.setMessage("成功");
            return notifyResult;
        } catch (Exception e) {
            response.setStatus(HttpStatus.HTTP_INTERNAL_ERROR);
            notifyResult.setCode("ERROR");
            notifyResult.setMessage("失败");
            return notifyResult;
        }

    }

    @PostMapping(value = "/wx/unifiedorder")
    @SaCheckLogin
    public Result wxUnifiedOrder(@RequestBody @Valid UnifiedOrderDTO unifiedOrderDTO) {
        Long orderId = unifiedOrderDTO.getId();
        Order order = new Order();
        order.setId(orderId);
        order.setUserId(StpUtil.getLoginIdAsLong());
        order.setStatus(OrderStatus.WAIT_PAY);
        Order order1 = orderData.queryByUserId(order);
        if (order1 == null) {
            return Result.failure("不存在的订单");
        }
        String redisKey = RedisKey.WX_PAY_ORDER + order1.getId();
        String prepayId = (String) redisUtil.get(redisKey);
        if (prepayId != null) {
            try {
                PayVO payVO = payService.buildPayVO(prepayId);
                return Result.content(payVO);
            } catch (Exception e) {
                return Result.failure("支付失败");
            }
        }
        PayVO result = payService.createOrder(order1);
        if (result == null) {
            return Result.failure("支付失败");
        }
        return Result.content(result);
    }

    @PostMapping(value = "/wx/close/order")
    @SaCheckLogin
    public Result wxCloseOrder(@RequestBody @Valid UnifiedOrderDTO unifiedOrderDTO) {
        Long orderId = unifiedOrderDTO.getId();
        Order order = new Order();
        order.setUserId(StpUtil.getLoginIdAsLong());
        order.setId(orderId);
        Order order1 = orderData.queryByUserId(order);
        if (order1 == null) {
            return Result.failure("不存在的订单");
        }
        boolean isClose = payService.closeOrder(order1);
        if (isClose) {
            Order updateOrder = new Order();
            updateOrder.setStatus(OrderStatus.HAS_CANCEL);
            updateOrder.setId(orderId);
            orderData.updateOrderStatus(updateOrder);
        }
        return isClose ? Result.success("关闭成功") : Result.failure("关闭失败");
    }
}
